Public Class ProductCodeClass
    Enum CodeVersion
        Version1 = 0
        Version2 = 1
        Version3 = 1
    End Enum
    'Public Enum ProductCodeResult
    '    InValidCode = 0
    '    ValidCode = 1
    'End Enum

    '          1  1    1 2   2   2 3 3
    '01234567890123456789012345678901234
    'XXXXX-YYYYY-XXXXX-YYYYY-XXXXX-YYYYY
    '---y- --y-- -m--- m---- d---d --c--
    'aaa0a-bb7bb-c0ccc-1dddd-0eee8-ff0ff = 07/01/08
    '                                  ^ Must be Alpha used for code version 
    '                        ^^^^^       Must be Numeric
    '^^                                  Product Code
    Public Function GenCode(ByVal ProductCode As String, ByVal ProductCodeDate As Date) As String
        Dim ProductCodeKey As String = "aaa0a-bb7bb-c0ccc-1dddd-0eee8-ff0ff"
        Try
            Dim sKey As String
            Dim CheckDigiStr As String
            sKey = Format(ProductCodeDate.Year, "0000")
            ProductCodeKey = ProductCode
            ProductCodeKey += GetRndChar() & sKey.Chars(2)
            ProductCodeKey += GetRndNum() & "-" & GetRndNum() & GetRndNum() & sKey.Chars(3) & GetRndNum() & GetRndNum() & "-" & GetRndNum()

            sKey = Format(ProductCodeDate.Month, "00")
            ProductCodeKey += sKey.Chars(0)
            ProductCodeKey += GetRndChar() & GetRndChar() & GetRndChar() & "-" & sKey.Chars(1)
            ProductCodeKey += GetRndChar() & GetRndChar() & GetRndChar() & GetRndChar() & "-"

            sKey = Format(ProductCodeDate.Day, "00")
            ProductCodeKey += sKey.Chars(0)
            ProductCodeKey += GetRndNum() & GetRndNum() & GetRndNum() & sKey.Chars(1)
            CheckDigiStr = ProductCodeKey.Chars(24) & ProductCodeKey.Chars(25) & ProductCodeKey.Chars(26) & ProductCodeKey.Chars(27)
            ProductCodeKey += "-" & GetRndNum() & GetRndNum() & GenCheckDigi(CheckDigiStr)
            ProductCodeKey += GetRndNum() & GetRndVersionChar()

        Catch ex As Exception
            Throw ex
        End Try
        Return UCase(ProductCodeKey)
    End Function

    Private Function GetDate(ByVal ProdCode As String) As String
        Try
            Dim sDate As String = ""
            sDate = ProdCode.Chars(24)
            sDate += ProdCode.Chars(28)
            sDate += "/"
            sDate += ProdCode.Chars(13)
            sDate += ProdCode.Chars(18)
            sDate += "/"
            sDate += ProdCode.Chars(3)
            sDate += ProdCode.Chars(8)
            If IsDate(sDate) Then
                sDate = FormatDateTime(CDate(sDate), DateFormat.ShortDate)
                Return sDate
            Else
                Return Nothing
            End If
        Catch ex As Exception
            Return Nothing
        End Try

    End Function

    Private Function GenCheckDigi(ByVal lCode As String) As String
        Dim rt As String = "0"
        Try
            Dim Res As Int32
            Dim ch As String
            ch = lCode.Chars(0)
            Res = CInt(ch)

            ch = lCode.Chars(1)
            Res += CInt(ch)

            ch = lCode.Chars(2)
            Res += CInt(ch)

            ch = lCode.Chars(3)
            Res += CInt(ch)
            If Res = 0 Then
                rt = "9"
            ElseIf (Res >= 8) And (Res < 18) Then
                rt = "7"
            ElseIf (Res >= 18) And (Res < 28) Then
                rt = "5"
            ElseIf (Res >= 28) And (Res < 30) Then
                rt = "3"
            Else 'Res = 34
                rt = "1"
            End If

        Catch ex As Exception
            Throw ex
        End Try
        Return rt
    End Function

    Private Function GetRndNum() As String
        Dim rt As String = "0"
        Try
            Dim value As Integer = CInt(Int((57 * Rnd()) + 1))
            Do While value < 48 Or value > 57
                value = CInt(Int((90 * Rnd()) + 1))
            Loop
            rt = Chr(value)
        Catch ex As Exception
            Throw ex
        End Try
        Return rt
    End Function
    Private Function GetRndVersionChar(Optional ByVal lCodeVersion As CodeVersion = CodeVersion.Version1) As String
        Dim rt As String = "0"
        Try
            If lCodeVersion = CodeVersion.Version1 Then
                Dim value As Integer = CInt(Int((70 * Rnd()) + 1))
                Do While value < 65 Or value > 70
                    value = CInt(Int((70 * Rnd()) + 1))
                Loop
                rt = Chr(value)
            End If

        Catch ex As Exception
            Throw ex
        End Try
        Return rt
    End Function

    Private Function GetRndChar() As String
        Dim rt As String = "0"
        Try
            Dim value As Integer = CInt(Int((90 * Rnd()) + 1))
            Do While value < 65 Or value > 90
                value = CInt(Int((90 * Rnd()) + 1))
            Loop
            rt = Chr(value)
        Catch ex As Exception
            Throw ex
        End Try
        Return rt
    End Function

    Public Function ValidateProductCode(ByVal ProductCode As String, Optional ByVal CheckDate As String = Nothing) As Boolean
        Try
            Dim lCheckDate As Date
            Dim sDate As String = GetDate(ProductCode)
            Dim CodeOk As Boolean = False
            If IsNothing(CheckDate) Then
                lCheckDate = Now()
            Else
                lCheckDate = CDate(CheckDate)
            End If
            If IsDate(sDate) Then
                If DateDiff(DateInterval.Day, CDate(sDate), lCheckDate) >= 0 Then
                    CodeOk = True
                Else
                    CodeOk = False
                End If
            Else
                Return False
            End If

            If CodeOk Then
                If Not IsNumeric(ProductCode.Chars(34)) Then
                    CodeOk = True
                Else
                    CodeOk = False
                End If

                If ProductCode.Chars(32) = GenCheckDigi(ProductCode.Chars(24) & ProductCode.Chars(25) & ProductCode.Chars(26) & ProductCode.Chars(27)) Then
                    Return True
                Else
                    Return False
                End If
            Else
                Return False
            End If

        Catch ex As Exception
            Return False
        End Try

    End Function
End Class
